<script setup lang="ts">
import {
  ComboboxAnchor,
  ComboboxContent,
  ComboboxInput,
  ComboboxPortal,
  ComboboxRoot,
  ComboboxTrigger,
  ComboboxViewport,
} from "radix-vue";

import { Icon } from "@iconify/vue";
import { ref } from "vue";
import { computed } from "vue";
import { watchEffect } from "vue";
import { onUnmounted } from "vue";

const icons = [
  "actionscript",
  "actionscript2",
  "ada",
  "advpl",
  "angular",
  "ansible",
  "antlr",
  "anyscript",
  "applescript",
  "appscript",
  "appsemble",
  "appveyor",
  "arduino",
  "asciidoc",
  "asp",
  "aspx",
  "astro",
  "astroconfig",
  "autohotkey",
  "autoit",
  "aws",
  "azure",
  "azurepipelines",
  "babel2",
  "bat",
  "befunge",
  "binary",
  "biome",
  "bitbucketpipeline",
  ["blade", "laravel"],
  "blitzbasic",
  "bolt",
  "browserslist",
  "bruno",
  "buckbuild",
  "buf",
  "bun",
  "bundler",
  "bunfig",
  "c-al",
  "c",
  "c2",
  "c3",
  "cabal",
  "caddy",
  "cake",
  "cakephp",
  "capacitor",
  "cargo",
  "casc",
  "cddl",
  "cert",
  "ceylon",
  "cheader",
  "chef-cookbook",
  "chef",
  "circleci",
  "class",
  "clojure",
  "clojurescript",
  "cloudfoundry",
  "cmake",
  "cobol",
  "codacy",
  "codeclimate",
  "codecov",
  "codekit",
  "codeowners",
  "codeql",
  "coffeelint",
  "coffeescript",
  "commitizen",
  "commitlint",
  "compass",
  "composer",
  "conan",
  "conda",
  "config",
  "confluence",
  "coveralls",
  "cpp",
  "cpp2",
  "cpp3",
  "cppheader",
  "crowdin",
  "crystal",
  "csharp",
  "csharp2",
  "cspell",
  "csproj",
  "css",
  "csscomb",
  "csslint",
  "cssmap",
  "cucumber",
  "cuda",
  "cvs",
  "cypress-spec",
  "cypress",
  "cython",
  "dal",
  "darcs",
  "dartlang-generated",
  "dartlang-ignore",
  "dartlang",
  "datadog",
  "db",
  "debian",
  "delphi",
  "deno",
  "denoify",
  "dependabot",
  "dependencies",
  "devcontainer",
  "dhall",
  "diff",
  "django",
  "dlang",
  "docker",
  "docker2",
  "dockertest",
  "dockertest2",
  "docpad",
  "docz",
  "dojo",
  "doppler",
  "dotenv",
  "dotjs",
  "doxygen",
  "drawio",
  "drone",
  "drools",
  "dustjs",
  "dvc",
  "dylan",
  "earthly",
  "eas-metadata",
  "edge",
  "edge2",
  "editorconfig",
  "eex",
  "ejs",
  "elastic",
  "elasticbeanstalk",
  "eleventy",
  "eleventy2",
  "elixir",
  "elm",
  "elm2",
  "emacs",
  "ember",
  "ensime",
  "erb",
  "erlang",
  "erlang2",
  "esbuild",
  "eslint",
  "eslint2",
  "esphome",
  "excalidraw",
  "excel",
  "excel2",
  "expo",
  "falcon",
  "fantasticon",
  "fauna",
  "favicon",
  "fbx",
  "firebase",
  "firebasehosting",
  "firestore",
  "fitbit",
  "fla",
  "flareact",
  "flash",
  "floobits",
  "flow",
  "flutter-package",
  "flutter",
  "font",
  "formkit",
  "fortran",
  "fossa",
  "fossil",
  "freemarker",
  "fsharp",
  "fsharp2",
  "fsproj",
  "fthtml",
  "funding",
  "fusebox",
  "galen",
  "galen2",
  "gamemaker",
  "gamemaker2",
  "gamemaker81",
  "gatsby",
  "gcloud",
  "gcode",
  "gdscript",
  "genstat",
  "git",
  "git2",
  "gitlab",
  "gitpod",
  "glide",
  "glitter",
  "glsl",
  "glyphs",
  "gnu",
  "gnuplot",
  "go-aqua",
  "go-fuchsia",
  "go-gopher",
  "go-lightblue",
  "go-package",
  "go-white",
  "go-work",
  "go-yellow",
  "go",
  "goctl",
  "godot",
  "gradle",
  "gradle2",
  "grain",
  "graphql-config",
  "graphql",
  "graphviz",
  "greenkeeper",
  "gridsome",
  "groovy",
  "groovy2",
  "grunt",
  "gulp",
  "haml",
  "handlebars",
  "handlebars2",
  "harbour",
  "hardhat",
  "hashicorp",
  "haskell",
  "haskell2",
  "haxe",
  "haxecheckstyle",
  "haxedevelop",
  "helix",
  "helm",
  "hjson",
  "hlsl",
  "homeassistant",
  "horusec",
  "host",
  "html",
  "htmlhint",
  "http",
  "hunspell",
  "husky",
  "hy",
  "hygen",
  "hypr",
  "icl",
  "idris",
  "idrisbin",
  "idrispkg",
  "image",
  "imba",
  "inc",
  "infopath",
  "informix",
  "ini",
  "ink",
  "innosetup",
  "io",
  "iodine",
  "ionic",
  "jake",
  "janet",
  "jar",
  "jasmine",
  "java",
  "jbuilder",
  "jekyll",
  "jenkins",
  "jest-snapshot",
  "jest",
  "jinja",
  "jpm",
  "js-official",
  "js",
  "jsbeautify",
  "jsconfig",
  "jscpd",
  "jshint",
  "jsmap",
  "json-official",
  "json-schema",
  "json",
  "json2",
  "json5",
  "jsonld",
  "jsonnet",
  "jsp",
  "jss",
  "juice",
  "julia2",
  "jupyter",
  "k",
  "karma",
  "key",
  "kitchenci",
  "kite",
  "kivy",
  "kos",
  "kotlin",
  "kusto",
  "latino",
  "layout",
  "lerna",
  "less",
  "lex",
  "license",
  "licensebat",
  "lighthouse",
  "lilypond",
  "lime",
  "lintstagedrc",
  "liquid",
  "lisp",
  "livescript",
  "lnk",
  "locale",
  "log",
  "lolcode",
  "lsl",
  "lua",
  "luau",
  "lync",
  "mailing",
  "manifest-bak",
  "manifest-skip",
  "manifest",
  "map",
  "mariadb",
  "markdown",
  "markdownlint-ignore",
  "markdownlint",
  "marko",
  "markojs",
  "master-co",
  "matlab",
  "maven",
  "maxscript",
  "maya",
  "mdx-components",
  "mdx",
  "mediawiki",
  "mercurial",
  "mermaid",
  "meson",
  "meteor",
  "mjml",
  "mlang",
  "mocha",
  "modernizr",
  "mojo",
  "mojolicious",
  "moleculer",
  "mondoo",
  "mongo",
  "monotone",
  "motif",
  "mson",
  "mustache",
  "mysql",
  "ndst",
  "nearly",
  "nest-adapter-js",
  "nest-adapter-ts",
  "nest-controller-js",
  "nest-controller-ts",
  "nest-decorator-js",
  "nest-decorator-ts",
  "nest-filter-js",
  "nest-filter-ts",
  "nest-gateway-js",
  "nest-gateway-ts",
  "nest-guard-js",
  "nest-guard-ts",
  "nest-interceptor-js",
  "nest-interceptor-ts",
  "nest-middleware-js",
  "nest-middleware-ts",
  "nest-module-js",
  "nest-module-ts",
  "nest-pipe-js",
  "nest-pipe-ts",
  "nest-service-js",
  "nest-service-ts",
  "nestjs",
  "netlify",
  "next",
  "ng-component-css",
  "ng-component-dart",
  "ng-component-html",
  "ng-component-js",
  "ng-component-js2",
  "ng-component-less",
  "ng-component-sass",
  "ng-component-scss",
  "ng-component-ts",
  "ng-component-ts2",
  "ng-controller-js",
  "ng-controller-ts",
  "ng-directive-dart",
  "ng-directive-js",
  "ng-directive-js2",
  "ng-directive-ts",
  "ng-directive-ts2",
  "ng-guard-dart",
  "ng-guard-js",
  "ng-guard-ts",
  "ng-interceptor-dart",
  "ng-interceptor-js",
  "ng-interceptor-ts",
  "ng-module-dart",
  "ng-module-js",
  "ng-module-js2",
  "ng-module-ts",
  "ng-module-ts2",
  "ng-pipe-dart",
  "ng-pipe-js",
  "ng-pipe-js2",
  "ng-pipe-ts",
  "ng-pipe-ts2",
  "ng-routing-dart",
  "ng-routing-js",
  "ng-routing-js2",
  "ng-routing-ts",
  "ng-routing-ts2",
  "ng-service-dart",
  "ng-service-js",
  "ng-service-js2",
  "ng-service-ts",
  "ng-service-ts2",
  "ng-smart-component-dart",
  "ng-smart-component-js",
  "ng-smart-component-js2",
  "ng-smart-component-ts",
  "ng-smart-component-ts2",
  "ng-tailwind",
  "nginx",
  "nim",
  "nimble",
  "ninja",
  "nix",
  "njsproj",
  "noc",
  "node",
  "node2",
  "nodemon",
  "npm",
  "nsi",
  "nsri-integrity",
  "nsri",
  "nuget",
  "numpy",
  "nunjucks",
  "nuxt",
  "nx",
  "nyc",
  "objectivec",
  "objectivecpp",
  "objidconfig",
  "ocaml-intf",
  "ocaml",
  "ogone",
  "onenote",
  "opencl",
  "openhab",
  "openscad",
  "org",
  "outlook",
  "ovpn",
  "package",
  "paket",
  "pandacss",
  "patch",
  "pcl",
  "pddl-happenings",
  "pddl-plan",
  "pddl",
  "pdf2",
  "pdm",
  "peeky",
  "perl",
  "perl2",
  "perl6",
  "pgsql",
  "php",
  "php2",
  "php3",
  "phpcsfixer",
  "phpstan",
  "phpunit",
  "phraseapp",
  "pine",
  "pip",
  "pipeline",
  "plantuml",
  "platformio",
  "playwright",
  "plsql-package-body",
  "plsql-package-header",
  "plsql-package-spec",
  "plsql-package",
  "plsql",
  "pm2",
  "pnpm",
  "poedit",
  "poetry",
  "polymer",
  "pony",
  "postcss",
  "postcssconfig",
  "postman",
  "powerpoint",
  "powerpoint2",
  "powershell-format",
  "powershell-psd",
  "powershell-psd2",
  "powershell-psm",
  "powershell-psm2",
  "powershell-types",
  "powershell",
  "powershell2",
  "preact",
  "precommit",
  "prettier",
  "prisma",
  "processinglang",
  "procfile",
  "progress",
  "prolog",
  "prometheus",
  "protobuf",
  "protractor",
  "publiccode",
  "publisher",
  "pug",
  "pulumi",
  "puppet",
  "purescript",
  "pyenv",
  "pyret",
  "python",
  "pythowo",
  "pytyped",
  "pyup",
  "q",
  "qbs",
  "qlikview",
  "qml",
  "qmldir",
  "qsharp",
  "quasar",
  "r",
  "racket",
  "rails",
  "rake",
  "raml",
  "razor",
  "razzle",
  "reactjs",
  "reacttemplate",
  "reactts",
  "reason",
  "red",
  "registry",
  "rego",
  "rehype",
  "remark",
  "renovate",
  "replit",
  "rescript",
  "rest",
  "retext",
  "rexx",
  "riot",
  "rmd",
  "robotframework",
  "robots",
  "rollup",
  "rome",
  "ron",
  "rproj",
  "rspec",
  "rubocop",
  "ruby",
  "rust-toolchain",
  "rust",
  "sails",
  "saltstack",
  "san",
  "sapphire-framework-cli",
  "sas",
  "sass",
  "sbt",
  "scala",
  "scilab",
  "script",
  "scss",
  "scss2",
  "sdlang",
  "sentry",
  "sequelize",
  "serverless",
  "shaderlab",
  "shell",
  "shuttle",
  "silverstripe",
  "sino",
  "siyuan",
  "sketch",
  "skipper",
  "slang",
  "slashup",
  "slice",
  "slim",
  "sln",
  "sln2",
  "smarty",
  "snapcraft",
  "snaplet",
  "snort",
  "snyk",
  "solidarity",
  "solidity",
  "source",
  "spacengine",
  "sparql",
  "spin",
  "sqf",
  "sql",
  "sqlite",
  "squirrel",
  "sss",
  "stan",
  "stata",
  "stencil",
  "storyboard",
  "storybook",
  "stryker",
  "stylable",
  "style",
  "styled",
  "stylelint",
  "stylish-haskell",
  "stylus",
  "sublime",
  "subversion",
  "svelte",
  "svelteconfig",
  "svg",
  "swagger",
  "swc",
  "swift",
  "swig",
  "symfony",
  "systemd",
  "systemverilog",
  "t4tt",
  "tailwind",
  "tamagui",
  "taskfile",
  "tauri",
  "tcl",
  "teal",
  "templ",
  "tera",
  "terraform",
  "test",
  "testcafe",
  "testjs",
  "testts",
  "tex",
  "text",
  "textile",
  "tfs",
  "tiltfile",
  "todo",
  "toit",
  "toml",
  "tox",
  "travis",
  "tree",
  "tres",
  "truffle",
  "trunk",
  "tsbuildinfo",
  "tscn",
  "tsconfig-official",
  "tsconfig",
  "tslint",
  "tt",
  "ttcn",
  "tuc",
  "turbo",
  "twig",
  "typedoc",
  "typescript-official",
  "typescript",
  "typescriptdef-official",
  "typescriptdef",
  "typo3",
  "uiua",
  "unibeautify",
  "unison",
  "unlicense",
  "unocss",
  "vagrant",
  "vala",
  "vanilla-extract",
  "vapi",
  "vapor",
  "vash",
  "vb",
  "vba",
  "vbhtml",
  "vbproj",
  "vcxproj",
  "velocity",
  "vento",
  "vercel",
  "verilog",
  "vhdl",
  "video",
  "view",
  "vim",
  "vite",
  "vitest",
  "vlang",
  "volt",
  "vscode-insiders",
  "vscode-test",
  "vscode",
  "vscode2",
  "vscode3",
  "vsix",
  "vsixmanifest",
  "vue",
  "vueconfig",
  "wallaby",
  "wally",
  "wasm",
  "watchmanconfig",
  "wdio",
  "webp",
  "webpack",
  "wenyan",
  "wercker",
  "wgsl",
  "wikitext",
  "windi",
  "wolfram",
  "word",
  "word2",
  "wpml",
  "wurst",
  "wxml",
  "wxss",
  "xcode",
  "xfl",
  "xib",
  "xliff",
  "xmake",
  "xml",
  "xorg",
  "xquery",
  "xsl",
  "yacc",
  "yaml",
  "yamllint",
  "yandex",
  "yang",
  "yarn",
  "yeoman",
  "zeit",
  "zig",
  "zip",
  "zip2",
];

const model = defineModel<string>();
const searchTerm = ref("");
const open = ref(false);
const limit = ref(80);
const list = computed(() =>
  icons
    .filter((icon) =>
      Array.isArray(icon)
        ? icon.some((i) =>
            i.toLowerCase().includes(searchTerm.value.toLowerCase()),
          )
        : icon.toLowerCase().includes(searchTerm.value.toLowerCase()),
    )
    .slice(0, limit.value),
);
const limitTimeout = ref();
watchEffect(() => {
  if (open.value) {
    searchTerm.value = "";
    limitTimeout.value = setTimeout(() => {
      limit.value = Infinity;
    }, 0);
  } else {
    clearTimeout(limitTimeout.value);
    limit.value = 80;
  }
});

onUnmounted(() => {
  clearTimeout(limitTimeout.value);
});
</script>

<template>
  <ComboboxRoot
    class="flex items-center"
    v-model:model-value="model"
    v-model:search-term="searchTerm"
    v-model:open="open"
  >
    <ComboboxAnchor class="flex items-center">
      <ComboboxTrigger>
        <Icon
          v-if="model"
          :icon="`vscode-icons:file-type-${model}`"
          class="-my-1 size-5"
        />
        <div
          v-else
          class="light:text-zinc-900 light:bg-zinc-300 light:hover:bg-zinc-200 relative -my-2 rounded bg-white/10 px-2 py-1 text-xs text-slate-300 hover:z-40 hover:bg-white/15"
        >
          Select icon
        </div>
      </ComboboxTrigger>
    </ComboboxAnchor>

    <ComboboxPortal>
      <ComboboxContent
        side="bottom"
        align="start"
        position="popper"
        :side-offset="5"
        class="z-[100] grid max-h-[calc(var(--radix-combobox-content-available-height)-16px)] min-w-[var(--radix-popper-anchor-width)] overflow-auto rounded-md border border-slate-700 bg-slate-800 font-mono antialiased shadow-[rgba(0,0,0,0.25)_0px_14px_28px,rgba(0,0,0,0.22)_0px_10px_10px]"
      >
        <div class="p-2">
          <ComboboxInput
            class="h-7 w-full shrink-0 rounded-md border border-slate-700 bg-slate-900 px-2 font-mono text-[12px] placeholder-slate-600/50 ring-blue-900/20 transition-colors hover:border-slate-600/40 focus:border-blue-800 focus:outline-none focus:ring-[3px]"
            placeholder="Search..."
          />
        </div>
        <ComboboxViewport class="-my-2 grid grid-cols-8 content-start p-2">
          <div
            class="col-span-8 grid h-6 cursor-pointer items-center px-2 text-xs font-medium transition-colors hover:text-white"
            v-if="list.length === 0"
          >
            No icons found for "{{ searchTerm }}"
          </div>
          <div
            :tabindex="0"
            v-for="item of list"
            :key="Array.isArray(item) ? item.join('') : item"
            :title="Array.isArray(item) ? item.join(', ') : item"
            class="cursor-pointer items-center rounded-md p-1.5 text-[13px] font-medium outline-none transition-colors hover:bg-slate-700 focus:ring-2 focus:ring-blue-800"
            @keydown.enter="
              () => {
                model = Array.isArray(item) ? item[0] : item;
                open = false;
              }
            "
            @click="
              () => {
                model = Array.isArray(item) ? item[0] : item;
                open = false;
              }
            "
          >
            <Icon
              :icon="`vscode-icons:file-type-${
                Array.isArray(item) ? item[0] : item
              }`"
              class="size-7 text-white"
            />
          </div>
        </ComboboxViewport>
        <div class="p-2">
          <div
            class="mt-2 flex h-7 cursor-pointer grid-cols-8 items-center rounded-md px-2 text-[13px] text-xs font-medium outline-none transition-colors hover:bg-slate-700 focus:ring-2 focus:ring-blue-800"
            v-if="model"
            :tabindex="0"
            @click="
              () => {
                model = '';
                open = false;
              }
            "
          >
            Remove icon
          </div>
        </div>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
